package messages;

import java.io.UnsupportedEncodingException;
import java.security.PrivateKey;
import java.security.PublicKey;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import connection.exception.ConnectionResetException;

import security.crypto.AssimEncryption;
import utils.Base64Processing;
import utils.Serialization;
import utils.XmlSerializationUtils;

public class CertSKExchangeMessage implements Convertible {

	private static final long serialVersionUID = 1L;
	
	private Integer _clientChallenge;
	private String _sessionKey;
	private String _cipheredSKMessage;

	public CertSKExchangeMessage() {}
	
	public CertSKExchangeMessage(Integer clientChallenge, SecretKey sessionKey, PublicKey clientPubKey){
		_clientChallenge = clientChallenge;
		_sessionKey = Base64Processing.encodeData(sessionKey.getEncoded());
		
		String serializedMessage = Serialization.SerializeAsXml(this);
		_cipheredSKMessage = AssimEncryption.cipher(serializedMessage, clientPubKey);
		
		_clientChallenge = null;
		_sessionKey = null;
	}
	
	public SecretKey getSessionKey(PrivateKey clientPrivateKey) throws ConnectionResetException {
		String serializedMessage = AssimEncryption.decipher(_cipheredSKMessage, clientPrivateKey);
		
		try {
			CertSKExchangeMessage skMessage = (CertSKExchangeMessage) Serialization.Deserialize(serializedMessage.getBytes("UTF-8"));
			_clientChallenge = skMessage._clientChallenge;
			_sessionKey = skMessage._sessionKey;
			
			return new SecretKeySpec(Base64Processing.decodeData(_sessionKey), "AES");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} 
		return null;
	}
	
	public Integer getClientChallenge(){
		return _clientChallenge;
	}

	public Element convertToCanonic(Document doc) {
		Element el = doc.createElement("CertSKExchangeMessage");

		if (_clientChallenge != null) {
			Element childEl = doc.createElement("ClientChallenge");
			childEl.setTextContent(_clientChallenge.toString());
			el.appendChild(childEl);
		}
		
		if (_sessionKey != null) {
			Element childEl = doc.createElement("SessionKey");
			childEl.setTextContent(_sessionKey);
			el.appendChild(childEl);
		}
		
		if (_cipheredSKMessage != null) {
			Element childEl = doc.createElement("CipheredSKMessage");
			childEl.setTextContent(_cipheredSKMessage);
			el.appendChild(childEl);
		}
		
		return el;
	}

	public Object convertFromCanonic(Element el) {
		this._clientChallenge = XmlSerializationUtils.getIntValue(el, "ClientChallenge");
		this._sessionKey = XmlSerializationUtils.getTextValue(el, "SessionKey");
		this._cipheredSKMessage = XmlSerializationUtils.getTextValue(el, "CipheredSKMessage");
		return this;
	}
}
